using System.Collections.Concurrent;
using Microsoft.Extensions.Options;
using RabbitMQ.Client;

namespace Aurora.RabbitMq.Provider;

/// <summary>
/// connection pool 
/// </summary>
public class ConnectionPool : IConnectionPool
{
    protected AuroraRabbitMqOptions Options { get; }

    protected ConcurrentDictionary<string, Lazy<IConnection>> Connections { get; }

    private bool _isDisposed;

    public ConnectionPool(IOptions<AuroraRabbitMqOptions> options)
    {
        this.Options = options.Value;
        Connections = new ConcurrentDictionary<string, Lazy<IConnection>>();
    }


    public void Dispose()
    {
        if (_isDisposed)
        {
            return;
        }

        _isDisposed = true;
        foreach (var connection in Connections.Values)
        {
            try
            {
                connection.Value.Dispose();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
    }

    public IConnection Get(string? connectionName = null)
    {
        connectionName ??= RabbitMqConst.DefaultConnectionName;
        try
        {
            var lazyConnection = Connections.GetOrAdd(connectionName, () =>
            {
                return new Lazy<IConnection>(() =>
                {
                    var connection = Options.Connections.GetOrDefault(connectionName);
                    var hostNames = connection.HostName.TrimEnd(';').Split(';');
                    return hostNames.Length == 1
                        ? connection.CreateConnection()
                        : connection.CreateConnection(hostNames);
                });
            });
            return lazyConnection.Value;
        }
        catch (Exception e)
        {
            Connections.TryRemove(connectionName, out _);
            throw;
        }
    }
}